﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PromoCodes_Models.Entities;
using PromoCodes_Models.Abstract;
using PromoCodes_GUI.Models;

namespace PromoCodes_GUI.Controllers
{
    public class SearchController : Controller
    {
        private IRepository<Promotion> _promoRepo;
        private List<SearchResult<Promotion>> searchResults = null;
        public SearchController(IRepository<Promotion> promoRepo)
        {
            _promoRepo = promoRepo;
        }

        public ActionResult Search(String search, int page = 1)
        {
            search = search.ToLower();
            List<String> searchValues = search.Split(' ').ToList();
            //removing 'worthless' words like articles if there is more than one keyword
            if (searchValues.Count > 1)
                searchValues.RemoveAll(x => x.ToLower().Equals("of") || x.ToLower().Equals("and") || x.ToLower().Equals("an") || x.ToLower().Equals("a") || x.ToLower().Equals("the"));
            List<SearchResult<Promotion>> results = new List<SearchResult<Promotion>>();
            List<Promotion> promotions = _promoRepo.Items.ToList();//Only query the database once
            foreach (var promotion in promotions)
            {
                int score = 0;
                //Adds for a perfect match on promotion code
                if (promotion.PromotionCode == search)
                    score += 45;
                //Adds for a perfect match with the product
                if (promotion.Product != null && promotion.Product.ProductName.ToLower() == search)
                    score += 25;
                //Adds for a perfect match with the discount type
                if (promotion.DiscountType.ToString().ToLower() == search)
                    score += 20;
                foreach (var searchVal in searchValues)
                {
                    //20 points for exact match of promo code with a single search keyword
                    //8 points for a partial match of promo code with a single search keyword
                    if (promotion.PromotionCode.ToLower() == searchVal)
                        score += 20;
                    else if (promotion.PromotionCode.ToLower().Contains(searchVal))
                        score += 8;
                    //8 points for exact match of product with a single search keyword
                    //5 points for a partial match of product with a single search keyword
                    if (promotion.Product != null && promotion.Product.ProductName.ToLower() == searchVal)
                        score += 8;
                    else if (promotion.Product != null && promotion.Product.ProductName.ToLower().Contains(searchVal))
                        score += 5;
                    //5 points for exact match with discount type
                    if (promotion.DiscountType.ToString().ToLower() == searchVal)
                        score += 5;
                }
                results.Add( new SearchResult<Promotion> { Result = promotion, Score = score});
            }
            searchResults = results.Where(x => x.Score > 0).OrderByDescending(x => x.Score).ThenBy(x => x.Result.Expiration).ToList();
            ListViewModel<SearchResult<Promotion>> model = new ListViewModel<SearchResult<Promotion>>()
            {
                Info = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = 20,
                    TotalItems = searchResults.Count
                },
                CurrentCategory = search,
                PageItems = searchResults.Skip(20 * (page - 1)).Take(20)
            };
            return View(model);
        }

        public ActionResult SearchBar()
        {
            return PartialView();
        }

    }
}
